package com.maikang.exammall.util;

import com.maikang.exammall.configuration.property.TxCosProperty;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.StorageClass;
import com.qcloud.cos.model.UploadResult;
import com.qcloud.cos.region.Region;
import com.qcloud.cos.transfer.TransferManager;
import com.qcloud.cos.transfer.Upload;
import lombok.SneakyThrows;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Component
@Log4j2
public class CosUtil {
    private final TxCosProperty cosProperty;
    private COSCredentials cred;
    private final COSClient cosClient;
    private ExecutorService threadPool = Executors.newFixedThreadPool(2);
    private TransferManager transferManager;

    private static final String userAvatarFolder = "user_avatar/";
    private static final String userCaptchaFolder = "user_captcha/";

    public CosUtil(TxCosProperty cosProperty) {
        this.cosProperty = cosProperty;
        this.cred = new BasicCOSCredentials(cosProperty.getSecretId(), cosProperty.getSecretKey());
        ClientConfig clientConfig = new ClientConfig(new Region(cosProperty.getRegion()));
        // 2 设置 bucket 的地域, COS 地域的简称请参照 https://cloud.tencent.com/document/product/436/6224
        // clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题 Java SDK 部分。
        // 这里建议设置使用 https 协议
//        clientConfig.setHttpProtocol(HttpProtocol.http);
        // 3 生成 cos 客户端。
        this.cosClient = new COSClient(cred, clientConfig);
        this.transferManager = new TransferManager(cosClient, threadPool);
    }

    @SneakyThrows
    public String upload(String path, File file) {
        PutObjectRequest putObjectRequest = new PutObjectRequest(cosProperty.getBucket(), path, file);
        return sendPutObjectRequest(path, putObjectRequest);
    }

    private String sendPutObjectRequest(String path, PutObjectRequest putObjectRequest) throws InterruptedException {
        putObjectRequest.setStorageClass(StorageClass.Standard_IA);

        String fileUrl = null;

        try {
            // 返回一个异步结果Upload, 可同步的调用waitForUploadResult等待upload结束, 成功返回UploadResult, 失败抛出异常.
            long startTime = System.currentTimeMillis();
            Upload upload = transferManager.upload(putObjectRequest);
            UploadResult uploadResult = upload.waitForUploadResult();
            long endTime = System.currentTimeMillis();
            fileUrl = cosProperty.getCommonBucketUrl() + "/" + path;
            log.info("etag: {}, fileUrl: {}, crc64 {}, it costs {} miliSeconds", uploadResult.getETag(), fileUrl, uploadResult.getCrc64Ecma(), endTime - startTime);
        } catch (CosClientException | InterruptedException e) {
            log.error("failed to upload {}", path, e);
            throw e;
        }
        return fileUrl;
    }

    @SneakyThrows
    public String upload(String path, MultipartFile file) {
        ObjectMetadata objectMetadata = new ObjectMetadata();
        objectMetadata.setContentType(file.getContentType());
        PutObjectRequest putObjectRequest = new PutObjectRequest(cosProperty.getBucket(), path, file.getInputStream(), objectMetadata);
        return sendPutObjectRequest(path, putObjectRequest);
    }

    @SneakyThrows
    public String upload(String path, BufferedImage img) {
        File outputFile = File.createTempFile("image" + System.currentTimeMillis() / 1000, ".jpg");
        ImageIO.write(img, "jpg", outputFile);
        String upload = upload(path, outputFile);
        if (outputFile.exists()) {
            outputFile.delete();
        }
        return upload;
    }

    public static String createUserAvatarStorePathFromMultipart(MultipartFile file, Long userId) {
        String oldFileName = file.getOriginalFilename();
        String eName = oldFileName.substring(oldFileName.lastIndexOf("."));
        String newFileName = "user_avatar_" + userId + eName;
        String key = userAvatarFolder + newFileName;
        return key;
    }

    public static String createUserCaptchaStorePathFromUserId(Long userId) {
        return userCaptchaFolder + userId + "_" + System.currentTimeMillis()/1000 + ".jpg";
    }

}
